

from sketchc import *

window = Window2((1000, 800))

class Blanket(Obj):
    def __init__(self, type, size, uv):
        assert len(uv) == 4
        self.type = type
        self.size = size
        self.uv = uv

        self.mode = moderngl.TRIANGLES
        self.t = Turtle()
        self.box = None

        self.prog = {
            "vertex_shader":'''
#version 330 core

in vec3 in_position;
in vec3 in_normal;
in vec2 in_texcoord_0;

uniform mat4 m_proj;
uniform mat4 m_model;
uniform mat4 m_cam;

out vec2 uv;

void main() {
    vec3 pos = vec3(in_position.x, in_position.y, in_position.z) + in_normal*0;
    gl_Position = m_proj * m_cam * m_model * vec4(pos, 1.0);

    uv = in_texcoord_0;
}
            ''',
            "fragment_shader":'''
#version 330 core
out vec4 fragColor;
uniform sampler2D texture0;
uniform vec2 texture0_size;

in vec2 uv;

void main()
{
    vec4 rgba = texture(texture0, uv / texture0_size);
    fragColor = vec4(rgba.rgb, rgba.a);
}

            ''',
        }

        self.texture = None
        self.texture_size = None
        self.vao = None

    def set_texture(self, texture, texture_size):
        self.texture = texture
        self.texture_size = np.array(texture_size, dtype="f4")

    def __rrshift__(self, obj):
        raise NotImplemented()

    def get_vao(self, ctx):
        c = rect(self.type, *self.size)        # 注意这里的顺序是逆时针序
        p2, p1, p3, p4 = c
        vertices = [p1, p4, p2, p1, p3, p4]
        normals = easy_norm(vertices)
        uv1, uv2, uv3, uv4 = self.uv
        uvs = [uv1, uv4, uv2, uv1, uv3, uv4 ]
        vertices = np.array(vertices, dtype="f4")
        normals = np.array(normals, dtype="f4")
        uvs = np.array(uvs, dtype="f4")
        a, b, c = vertices[:,0], vertices[:,1], vertices[:,2]
        d, e, f = normals[:,0], normals[:,1], normals[:,2]
        g, h = uvs[:,0], uvs[:,1]
        x = np.dstack([a, b, c, d, e, f, g, h])
        vbo = ctx.buffer(x.astype("f4"))
        return ctx.simple_vertex_array(self.prog, vbo,  'in_position', 'in_normal', 'in_texcoord_0')

    def u(self, ctx):
        assert isinstance(ctx, moderngl.Context)
        self.prog = ctx.program(**self.prog)
        self.vao= self.get_vao(ctx)

    def draw(self, camera):
        if self.vao is None:
            print("没准备好绘制", self)
            return

        self.prog['m_proj'].write(camera.p())
        self.prog['m_model'].write(self.m())
        self.prog['m_cam'].write(camera.v())
        self.prog['texture0'].value = 1
        self.texture.use(1)
        self.prog['texture0_size'].write(np.array(self.texture_size, dtype="f4"))
        self.vao.render(self.mode)

    def draw_normal(self, camera):
        return



b1 = Blanket("xy", (3, 10), [(0, 100), (30, 100), (0, 0), (30, 0)])


# ~ pic = pygame.image.load("texture1.png")
# ~ texture = window.ctx.texture(pic.get_size(), 4)
# ~ texture_data = pic.get_view('1')      # 这个接口真变态啊
# ~ texture.write(texture_data)
# ~ b1.set_texture(texture, (2, 1))

# ~ pic = pygame.image.load("texture2.png")
# ~ texture = window.ctx.texture(pic.get_size(), 4)
# ~ texture_data = pic.get_view('1')      # 这个接口真变态啊
# ~ texture.write(texture_data)
# ~ b1.set_texture(texture, (3, 1.73))


# ~ pic = pygame.image.load("texture3.png")
# ~ texture = window.ctx.texture(pic.get_size(), 4)
# ~ texture_data = pic.get_view('1')      # 这个接口真变态啊
# ~ texture.write(texture_data)
# ~ b1.set_texture(texture, (1, 1))

# ~ pic = pygame.image.load("texture4.png")
# ~ texture = window.ctx.texture(pic.get_size(), 4)
# ~ texture_data = pic.get_view('1')      # 这个接口真变态啊
# ~ texture.write(texture_data)
# ~ b1.set_texture(texture, (1, 1.73))

pic = pygame.image.load("texture5.png")
texture = window.ctx.texture(pic.get_size(), 4)
texture_data = pic.get_view('1')      # 这个接口真变态啊
texture.write(texture_data)
b1.set_texture(texture, (4, 4))

b1.u(window.ctx)
b1 >> window

camera = Camera(U3(0, -5, 1))
camera >> window        # 识别为camera则自动作为主camera

walker = Walker(camera)
walker >> window


clock = pygame.time.Clock()
while True:
    dt = clock.tick(60)
    window.update(dt)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            exit()
        window.dispatch(e)
    window.render()   # screen 操作需要写在window的槽里
    pygame.display.flip()

